#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define MAX 1024
#define ARGC 64
#define SEP " "

int split(char *commandstr, char *argv[])
{
    assert(commandstr);
    assert(argv);

    argv[0] = strtok(commandstr, SEP);
    if(argv[0] == NULL) return -1;
    int i = 1;
    while((argv[i++] = strtok(NULL, SEP)));
    //int i = 1;
    //while(1)
    //{
    //    argv[i] = strtok(NULL, SEP);
    //    if(argv[i] == NULL) break;
    //    i++;
    //}
    return 0;
}

void debugPrint(char *argv[])
{
    for(int i = 0; argv[i]; i++)
    {
        printf("%d: %s\n", i, argv[i]);
    }
}

void showEnv(){
  extern char**environ;
  for(int i = 0;environ[i];i++){
    printf("%d:%s\n",i,environ[i]);
  }
}

int main()
{
    while(1)
    {
        char commandstr[MAX] = {0};
        char *argv[ARGC] = {NULL};
        printf("[Eclips3@mymachine currpath]-> ");
        fflush(stdout);
        char *s = fgets(commandstr, sizeof(commandstr), stdin);
        assert(s);
        //使用一次s，避免在release版本下由于去掉了assert导致s没被使用而带来的编译告警
        (void)s;
        // abcd\n\0
        commandstr[strlen(commandstr)-1] = '\0';
        // "ls -a -l" -> "ls" "-a" "-l"
        int n = split(commandstr, argv);
        if(n != 0) continue;
        //version 2：添加颜色 -- 在末尾添加颜色命令
        if(strcmp(argv[0],"ls")==0){
            int pos = 0;
            while(argv[pos]){
              pos++;
            }
            argv[pos++] = (char*)"--color=auto";
            argv[pos] = NULL;

        }

        //version 3：执行命令的是子进程，cd的时候子进程cd了但是父进程没有，所以有些命令不能给子进程执行，这种命令叫做内建/内置命令
        //让bash自己调用对应的函数改变工作路径
        if(strcmp(argv[0],"cd")==0){
          if(argv[1]!=NULL){
            chdir(argv[1]);
          }
          continue;
        }else if(strcmp(argv[0],"export")==0){
          //设置环境变量（环境变量是为父进程设置的）
          if(argv[1]!=NULL){
            putenv(argv[1]);   
          }
          continue;
        }else if(strcmp(argv[0],"env")==0){
          showEnv();
          continue;
        }else if(strcmp(argv[0],"echo")==0){
          //echo $PATH
          const char *target_env = NULL;
          if(*argv[1]=='$'){
              target_env = getenv(argv[1]+1);;
          }
          if(target_env != NULL){
            printf("%s=%s\n",argv[1]+1,target_env);
          }
          continue;
        }
        

        //debugPrint(argv);
        //version 1
        pid_t id = fork();
        assert(id >= 0);
        (void)id;

        if(id == 0)
        {
            //child
            execvp(argv[0], argv);
            exit(1);
        }
        int status = 0;
        waitpid(id, &status, 0);
        //printf("%s\n", commandstr);
    }
}
